/*****************************************************************************
*    Copyright (C)2008 Ali Corporation. All Rights Reserved.
*
*    File:    tun_rt820.c
*
*    Description:    This file contains alpstdae basic function in LLD. 
*    History:
*           Date            Athor        Version          Reason
*	    ============	=============	=========	=================
*	1.  20080520		Trueve Hu		 Ver 0.1	Create file.
*	
*****************************************************************************/

#include <sys_config.h>
#include <retcode.h>
#include <types.h>

#include <api/libc/printf.h>
#include <api/libc/string.h>
#include <bus/i2c/i2c.h>
#include <osal/osal_task.h>

#include "tun_mxl603.h"
#include "MxL603_TunerApi.h"
#include "MxL603_OEM_Drv.h"

#define MXL603_PRINTF(...)	do{}while(0) //libc_printf
//#define MXL603_PRINTF	printk //libc_printf
#define printf				MXL603_PRINTF

static struct QAM_TUNER_CONFIG_EXT * mxl603_dev_id[MAX_TUNER_SUPPORT_NUM] = {NULL};
static UINT32 mxl603_tuner_cnt = 0;
static UINT8 mxl603_reg_ini[2]={0,0};

INT32 tun_mxl603_init(UINT32* tuner_id, struct QAM_TUNER_CONFIG_EXT * ptrTuner_Config)
{
	/* check Tuner Configuration structure is available or not */
	if ((ptrTuner_Config == NULL) || (mxl603_tuner_cnt>=MAX_TUNER_SUPPORT_NUM))
		return ERR_FAILUE;

	mxl603_dev_id[mxl603_tuner_cnt] = ptrTuner_Config;
	*tuner_id = mxl603_tuner_cnt; // here, means mxl603's devId.

	mxl603_reg_ini[mxl603_tuner_cnt]=0;		// status bit for initialized rt820 register
	mxl603_tuner_cnt ++;

	return SUCCESS;
}

INT32 tun_mxl603_status(UINT32 tuner_id, UINT8 *lock)
{
	INT32 result;

	MXL_STATUS status; 
	UINT8 devId;

	UINT8 refLockPtr = MXL_UNLOCKED;
	UINT8 rfLockPtr = MXL_UNLOCKED;		

	devId = (UINT8)(tuner_id & 0xff);
	
	// Read back Tuner lock status
	status = MxLWare603_API_ReqTunerLockStatus(devId, &rfLockPtr, &refLockPtr);
	if (status == MXL_TRUE)
	{
		MXL603_PRINTF("mxl603 get lock status: %d, %d !\n", rfLockPtr, refLockPtr);
	
		if ((MXL_LOCKED == rfLockPtr) && (MXL_LOCKED == refLockPtr))
		{
			*lock = 1;
			MXL603_PRINTF("Tuner locked\n");
		}
		else
		{
			*lock = 0;
			MXL603_PRINTF("Tuner unlocked__1!\n");
		}
	}
	else
	{
		*lock = 0;
		return ERR_FAILUE;
	}
	

	return SUCCESS;
}

INT32 tun_mxl603_get_rf_level(UINT32 tuner_id, UINT32 *type, UINT32 *rf_level)// return level in dbuV.
{
	INT32 result;

	MXL_STATUS status; 
	UINT8 devId;

	INT32 rf_info = 0;		

	*type = 0;	/* When type is 0, rf_level value is Signal level in dBuv , add by Artie 20120618 */
	devId = (UINT8)(tuner_id & 0xff);
	
	// Read back Tuner RF level.
	status = MxLWare603_API_ReqTunerRxPower(devId, &rf_info);
	if (status == MXL_TRUE)
	{
		MXL603_PRINTF("mxl603 get RF level: %d dbm !\n", rf_info);
		*rf_level = (UINT32)(rf_info + 107); // shift from dbm to dbuV.
		MXL603_PRINTF("mxl603 get RF level: %d dbuV !\n", *rf_level);
			
	}
	else
	{
		*rf_level = 0;
		return ERR_FAILUE;
	}
	

	return SUCCESS;
}

INT32 tun_mxl603_control(UINT32 tuner_id, UINT32 freq, UINT32 sym, UINT8 AGC_Time_Const, UINT8 _i2c_cmd)	
{	
	INT32 result;

	MXL_STATUS status; 
	UINT8 devId;
	MXL603_CHAN_TUNE_CFG_T chanTuneCfg;

	struct QAM_TUNER_CONFIG_EXT * tuner_dev_ptr = NULL;

	if ((tuner_id>=mxl603_tuner_cnt) || (tuner_id>=MAX_TUNER_SUPPORT_NUM))
		return ERR_FAILUE;
	tuner_dev_ptr = mxl603_dev_id[tuner_id];

	devId= (UINT8)(tuner_id & 0xff);

	if(0==mxl603_reg_ini[tuner_id])
	{
		MXL_BOOL singleSupply_3_3V;
		MXL603_XTAL_SET_CFG_T xtalCfg;
		MXL603_IF_OUT_CFG_T ifOutCfg;
		MXL603_AGC_CFG_T agcCfg;
		MXL603_TUNER_MODE_CFG_T tunerModeCfg;
	
		//step 0. Init device.
	    status = MxLWare603_API_CfgDrvInit(devId, NULL);  

		//Step 1 : Soft Reset MxL603
		status = MxLWare603_API_CfgDevSoftReset(devId);
		if (status != MXL_SUCCESS)
		{
		printf("Error! MxLWare603_API_CfgDevSoftReset\n");    
		}

		//Step 2 : Overwrite Default
		singleSupply_3_3V = MXL_ENABLE;
		status = MxLWare603_API_CfgDevOverwriteDefaults(devId, singleSupply_3_3V);
		if (status != MXL_SUCCESS)
		{
		printf("Error! MxLWare603_API_CfgDevOverwriteDefaults\n");    
		}

		//Step 3 : XTAL Setting
		xtalCfg.xtalFreqSel = MXL603_XTAL_16MHz; // According to 16M accuracy.
		xtalCfg.xtalCap = 12;
		xtalCfg.clkOutEnable = MXL_DISABLE;
		xtalCfg.clkOutDiv = MXL_DISABLE;
		xtalCfg.clkOutExt = MXL_DISABLE;
		xtalCfg.singleSupply_3_3V = MXL_ENABLE;
		xtalCfg.XtalSharingMode = MXL_DISABLE;
		status = MxLWare603_API_CfgDevXtal(devId, xtalCfg);
		if (status != MXL_SUCCESS)
		{
		printf("Error! MxLWare603_API_CfgDevXtal\n");    
		}

		//Step 4 : IF Out setting
		if (tuner_dev_ptr->wTuner_IF_Freq < 5200) // 8m mode, for 6M/8M mode tmp code.
		{
			ifOutCfg.ifOutFreq = MXL603_IF_5MHz;
		}
		else
		{
			ifOutCfg.ifOutFreq = MXL603_IF_5_38MHz;
		}
		
		ifOutCfg.ifInversion = MXL_DISABLE;
		ifOutCfg.gainLevel = 6; // 6 for 1Vpp.
		ifOutCfg.manualFreqSet = MXL_DISABLE;
		ifOutCfg.manualIFOutFreqInKHz = 0;
		status = MxLWare603_API_CfgTunerIFOutParam(devId, ifOutCfg);
		if (status != MXL_SUCCESS)
		{
		printf("Error! MxLWare603_API_CfgTunerIFOutParam\n");    
		}

		//Step 5 : AGC Setting
		agcCfg.agcType = MXL603_AGC_SELF;
		agcCfg.setPoint = 66;
		agcCfg.agcPolarityInverstion = MXL_DISABLE; // disable for positive slope.
		status = MxLWare603_API_CfgTunerAGC(devId, agcCfg);
		if (status != MXL_SUCCESS)
		{
		printf("Error! MxLWare603_API_CfgTunerAGC\n");    
		}

		//Step 6 : Application Mode setting
		tunerModeCfg.signalMode = MXL603_DIG_DVB_C;

		if (tuner_dev_ptr->wTuner_IF_Freq < 5200) // 8m mode, for 6M/8M mode tmp code.
		{
			tunerModeCfg.ifOutFreqinKHz = 5000;
		}
		else
		{
			tunerModeCfg.ifOutFreqinKHz = 5380;
		}
		
		tunerModeCfg.xtalFreqSel = MXL603_XTAL_16MHz;
		tunerModeCfg.ifOutGainLevel = 11;
		status = MxLWare603_API_CfgTunerMode(devId, tunerModeCfg);
		if (status != MXL_SUCCESS)
		{
		printf("Error! MxLWare603_API_CfgTunerMode\n");    
		}

        MXL603_PRINTF("Initialze OK of Mxl603! \n");

		mxl603_reg_ini[tuner_id]=1;
	}


	//Step 7 : Channel frequency & bandwidth setting
	if (tuner_dev_ptr->wTuner_IF_Freq < 5200) // 8m mode, for 6M/8M mode tmp code.
	{
		chanTuneCfg.bandWidth = MXL603_CABLE_BW_8MHz;
	}
	else
	{
		chanTuneCfg.bandWidth = MXL603_CABLE_BW_6MHz;
	}
	
	chanTuneCfg.freqInHz = (freq * 1000);
	chanTuneCfg.signalMode = MXL603_DIG_DVB_C;
	chanTuneCfg.xtalFreqSel = MXL603_XTAL_16MHz;
	chanTuneCfg.startTune = MXL_START_TUNE;
	status = MxLWare603_API_CfgTunerChanTune(devId, chanTuneCfg);
	if (status != MXL_SUCCESS)
	{
	printf("Error! MxLWare603_API_CfgTunerChanTune\n");    
	}

	// Wait 15 ms 
	MxLWare603_OEM_Sleep(15);
	//MxLWare603_OEM_Sleep(200);
	
	return SUCCESS;

}


MXL_STATUS MxLWare603_OEM_WriteRegister(UINT8 devId, UINT8 RegAddr, UINT8 RegData)
{
	INT32 result;
	MXL_STATUS status = MXL_FAILED;

	struct QAM_TUNER_CONFIG_EXT * tuner_dev_ptr = NULL;
	UINT8 data_tmp[2];
	
	tuner_dev_ptr = mxl603_dev_id[devId];

	data_tmp[0] = RegAddr;
	data_tmp[1] = RegData;
	
  	//result = ali_i2c_scb_write(tuner_dev_ptr->i2c_type_id, tuner_dev_ptr->cTuner_Base_Addr, data_tmp, 2);
  	result = i2c_write(tuner_dev_ptr->i2c_type_id, tuner_dev_ptr->cTuner_Base_Addr, data_tmp, 2);
	
    //MXL603_PRINTF("I2C write operation _0, Id= %d, Ret = %d ! \n", tuner_dev_ptr->i2c_type_id, result);

	if (SUCCESS == result)
	{
		status = MXL_SUCCESS;
	}
	else
	{
        MXL603_PRINTF("I2C write failed! \n");
		status = MXL_FAILED;
	}
	//return status;
	return MXL_SUCCESS;
}

MXL_STATUS MxLWare603_OEM_ReadRegister(UINT8 devId, UINT8 RegAddr, UINT8 *DataPtr)
{

	INT32 result;
	MXL_STATUS status = MXL_FAILED;

	struct QAM_TUNER_CONFIG_EXT * tuner_dev_ptr = NULL;
	UINT8 data_tmp[2];
	
	tuner_dev_ptr = mxl603_dev_id[devId];

	data_tmp[0] = 0xfb;
	data_tmp[1] = RegAddr;

  	//result = ali_i2c_scb_write(tuner_dev_ptr->i2c_type_id, tuner_dev_ptr->cTuner_Base_Addr, data_tmp, 2);
	result = i2c_write(tuner_dev_ptr->i2c_type_id, tuner_dev_ptr->cTuner_Base_Addr, data_tmp, 2);
	
    //MXL603_PRINTF("I2C read operation _1, Ret = %d ! \n", result);

	if (SUCCESS != result)
	{	
        MXL603_PRINTF("I2C read failed_1 ! \n");
		//return MXL_FAILED;
	}

	//result = ali_i2c_scb_read(tuner_dev_ptr->i2c_type_id, tuner_dev_ptr->cTuner_Base_Addr, DataPtr, 1);
	result = i2c_read(tuner_dev_ptr->i2c_type_id, tuner_dev_ptr->cTuner_Base_Addr, DataPtr, 1);

    //MXL603_PRINTF("I2C read operation _2, Ret = %d ! \n", result);

	if (SUCCESS == result)
	{
		status = MXL_SUCCESS;
	}
	else
	{
        MXL603_PRINTF("I2C read failed_2 ! \n");
	
		status = MXL_FAILED;
	}

	//return status;
	return MXL_SUCCESS;

}

void MxLWare603_OEM_Sleep(UINT16 DelayTimeInMs)
{
	//msleep(DelayTimeInMs);  
	osal_task_sleep(DelayTimeInMs);
}

//this code is from linux env, modify to tds.
/*
extern struct ali_nim_m3200_private *ali_m3200_nim_priv;
static int __devinit ali_tuner_mxl603_init(void)
{
    struct ali_nim_m3200_private *priv = NULL;
    if (NULL!=ali_m3200_nim_priv)
    {
        priv=ali_m3200_nim_priv;
    }
    else
    {
        MXL603_PRINTF("No Ali M3200 NIM device available.\n");
        return -ENODEV;
    }
    priv->nim_Tuner_Init=tun_mxl603_init;
    priv->nim_Tuner_Control=tun_mxl603_control;
    priv->nim_Tuner_Status=tun_mxl603_status;
    ali_nim_m3200_cfg_tuner(MXL603);
    return RET_SUCCESS;
}

static void __exit ali_tuner_mxl603_exit(void)
{
    struct ali_nim_m3200_private *priv = NULL;
    if (NULL!=ali_m3200_nim_priv)
    {
        priv=ali_m3200_nim_priv;
    }
    else
    {
        MXL603_PRINTF("No Ali M3200 NIM device available.\n");
        return;
    }
    priv->nim_Tuner_Init = NULL;
    priv->nim_Tuner_Control = NULL;
    priv->nim_Tuner_Status = NULL;
    ali_nim_m3200_cfg_tuner(NULL);
}

module_init(ali_tuner_mxl603_init);
module_exit(ali_tuner_mxl603_exit);

*/

